const neo4j = require('neo4j-driver');
const { Op } = require('sequelize');

class RecommendService {
    constructor(neo4jDriver, sequelize) {
        this.neo4jDriver = neo4jDriver;
        this.sequelize = sequelize;
    }

    // 记录用户行为
    async recordUserAction(userId, goodsId, actionType) {
        // 1. 在MySQL中记录用户行为
        const UserAction = this.sequelize.models.user_actions;
        await UserAction.create({
            user_id: userId,
            goods_id: goodsId,
            action_type: actionType
        });
        
        // 2. 在Neo4j中创建/更新用户-商品关系
        const session = this.neo4jDriver.session();
        try {
            // 确保用户节点存在
            await session.run(`
                MERGE (u:User {id: $userId})
            `, { userId });
            
            // 根据行为类型创建不同的关系
            let relationshipType;
            switch(actionType) {
                case 'view':
                    relationshipType = 'VIEWED';
                    break;
                case 'collect':
                    relationshipType = 'COLLECTED';
                    break;
                case 'share':
                    relationshipType = 'SHARED';
                    break;
                default:
                    relationshipType = 'INTERACTED_WITH';
            }
            
            // 创建或更新关系，带上时间戳
            await session.run(`
                MATCH (u:User {id: $userId})
                MATCH (g:Goods {id: $goodsId})
                MERGE (u)-[r:${relationshipType}]->(g)
                SET r.timestamp = timestamp(), 
                    r.count = CASE WHEN r.count IS NULL THEN 1 ELSE r.count + 1 END
            `, { userId, goodsId });
            
        } finally {
            await session.close();
        }
    }

    // 获取用户最近浏览的商品类型和标签
    async getUserPreferences(userId) {
        try {
        const UserAction = this.sequelize.models.user_actions;
        const Goods = this.sequelize.models.goods;
            const Type = this.sequelize.models.type;
        const Tag = this.sequelize.models.tag;

            // 获取用户最近的行为记录 - 修改关联查询方式
        const recentActions = await UserAction.findAll({
            where: { user_id: userId },
            order: [['action_time', 'DESC']],
            limit: 10
        });

            // 从行为记录中提取商品ID
            const goodsIds = recentActions.map(action => action.goods_id);
            
            // 如果没有行为记录，返回空结果
            if (goodsIds.length === 0) {
                return { types: [], tags: [] };
            }
            
            // 分别查询商品和标签
            const goodsDetails = await Goods.findAll({
                where: { id: goodsIds },
                attributes: ['id', 'type']
            });
            
            // 提取类型
            const types = new Set(goodsDetails.map(goods => goods.type));
            
            // 获取与这些商品关联的标签
            const goodsTags = await this.sequelize.models.goods_tag.findAll({
                where: { goods_id: goodsIds }
            });
            
            // 提取标签ID
            const tagIds = new Set(goodsTags.map(gt => gt.tag_id));

        return {
            types: Array.from(types),
                tags: Array.from(tagIds)
        };
        } catch (error) {
            console.error('获取用户偏好失败:', error);
            return { types: [], tags: [] };
        }
    }

    // 基于知识图谱的推荐
    async getRecommendations(userId) {
        const session = this.neo4jDriver.session();
        try {
            // 获取用户偏好
            const preferences = await this.getUserPreferences(userId);
            
            // 查询基于用户收藏的推荐
            const collectQuery = `
                // 查找用户收藏的商品
                MATCH (u:User {id: $userId})-[c:COLLECTED]->(collected:Goods)
                WITH u, collected
                ORDER BY c.timestamp DESC
                LIMIT 5
                
                // 找出与收藏商品相关的其他商品
                MATCH (collected)-[:BELONGS_TO_REGION|BELONGS_TO_SCHOOL|BELONGS_TO_PERIOD|RELATED_TO_FIGURE|RELATED_TO_EVENT]->(common)
                <-[:BELONGS_TO_REGION|BELONGS_TO_SCHOOL|BELONGS_TO_PERIOD|RELATED_TO_FIGURE|RELATED_TO_EVENT]-(recGoods:Goods)
                WHERE NOT (u)-[:VIEWED]->(recGoods) AND recGoods <> collected
                
                // 计算相关度分数
                WITH recGoods, common, collected, count(common) as commonCount, labels(common)[0] as commonType
                ORDER BY commonCount DESC
                
                // 返回推荐结果
                RETURN DISTINCT recGoods.id as id, 
                       recGoods.name as name, 
                       recGoods.cover as cover,
                       collect(DISTINCT {type: commonType, name: common.name}) as reasons,
                       commonCount as relevanceScore
                ORDER BY relevanceScore DESC
                LIMIT 8
            `;
            
            // 先查询基于收藏的推荐
            let result = await session.run(collectQuery, { userId });
            
            // 如果收藏推荐不足，再查询基于浏览的推荐
            if (result.records.length < 5) {
                // 构建查询 - 基于浏览历史的推荐
                const viewQuery = `
                    // 查找用户最近查看的商品
                    MATCH (u:User {id: $userId})-[v:VIEWED]->(recent:Goods)
                    WITH u, recent
                    ORDER BY v.timestamp DESC
                    LIMIT 5
                    
                    // 找出同类型或同地区的相关商品
                    MATCH (recent)-[:BELONGS_TO_REGION|BELONGS_TO_SCHOOL|BELONGS_TO_PERIOD]->(common)
                    <-[:BELONGS_TO_REGION|BELONGS_TO_SCHOOL|BELONGS_TO_PERIOD]-(recGoods:Goods)
                    WHERE NOT (u)-[:VIEWED]->(recGoods) AND recGoods <> recent
                    
                    // 计算相关度分数
                    WITH recGoods, common, recent, count(common) as commonCount
                    ORDER BY commonCount DESC
                    
                    // 限制推荐数量
                    RETURN DISTINCT recGoods.id as id, 
                           recGoods.name as name, 
                           recGoods.cover as cover,
                           collect(DISTINCT {type: labels(common)[0], name: common.name}) as reasons,
                           commonCount as relevanceScore
                    ORDER BY relevanceScore DESC
                    LIMIT 8
                `;
                
                const viewResult = await session.run(viewQuery, { userId });
                
                // 合并结果 (防止重复)
                const recommendedIds = new Set(result.records.map(record => record.get('id')));
                const combinedRecords = [...result.records];
                
                for (const record of viewResult.records) {
                    const id = record.get('id');
                    if (!recommendedIds.has(id)) {
                        recommendedIds.add(id);
                        combinedRecords.push(record);
                    }
                }
                
                result = { records: combinedRecords.slice(0, 8) };
            }
            
            // 如果推荐结果仍然不足，使用基于类型和标签的兜底推荐
            if (result.records.length < 3) {
                const fallbackQuery = `
                    MATCH (g:Goods)
                    WHERE g.type IN $types OR EXISTS {
                        MATCH (g)-[:HAS_TAG]->(t:Tag)
                        WHERE t.id IN $tags
                    }
                    AND NOT g.id IN $existingIds
                    RETURN g.id as id, g.name as name, g.cover as cover, 
                           [] as reasons, 1 as relevanceScore
                    LIMIT 8
                `;
                
                const existingIds = result.records.map(record => record.get('id'));
                
                const fallbackResult = await session.run(fallbackQuery, {
                    types: preferences.types.length > 0 ? preferences.types : [-1], // 避免空数组
                    tags: preferences.tags.length > 0 ? preferences.tags : [-1],    // 避免空数组
                    existingIds: existingIds.length > 0 ? existingIds : [-1]        // 避免空数组
                });
                
                // 如果还是没有足够的推荐，获取热门商品
                if (result.records.length + fallbackResult.records.length < 3) {
                    const popularItems = await this.getPopularItems();

            // 处理推荐结果
                    const recommendations = result.records.map(record => ({
                        id: record.get('id'),
                        name: record.get('name'),
                        cover: record.get('cover'),
                        reasons: record.get('reasons'),
                        relevanceScore: record.get('relevanceScore').toNumber()
                    }));
                    
                    // 添加标签推荐商品
                    fallbackResult.records.forEach(record => {
                        recommendations.push({
                            id: record.get('id'),
                            name: record.get('name'),
                            cover: record.get('cover'),
                            reasons: ['您可能感兴趣'],
                            relevanceScore: 1
                        });
                    });
                    
                    // 添加热门商品，避免重复
                    const recommendedIds = new Set(recommendations.map(item => item.id));
                    for (const item of popularItems) {
                        if (!recommendedIds.has(item.id) && recommendations.length < 8) {
                            recommendedIds.add(item.id);
                            recommendations.push(item);
                        }
                    }
                    
                    return recommendations;
                }
                
                // 合并结果
                result = { 
                    records: [...result.records, ...fallbackResult.records].slice(0, 8) 
                };
            }

            // 处理推荐结果
            return result.records.map(record => ({
                id: record.get('id'),
                name: record.get('name'),
                cover: record.get('cover'),
                reasons: record.get('reasons'),
                relevanceScore: record.get('relevanceScore').toNumber()
            }));
        } catch (error) {
            console.error('获取推荐失败:', error);
            // 发生错误时返回热门推荐作为兜底
            return await this.getPopularItems();
        } finally {
            await session.close();
        }
    }

    // 基于历史文化背景的推荐
    async getHistoricalRecommendations(userId) {
        const session = this.neo4jDriver.session();
        try {
             // 查找用户最近浏览的工艺品
            // 改进历史文化背景推荐查询 
            const query = `
                MATCH (u:User {id: $userId})-[v:VIEWED]->(recent:Goods)
                WITH u, recent
                ORDER BY v.timestamp DESC
                LIMIT 3
                
                // 找出与浏览商品有相同文化关系的商品
                OPTIONAL MATCH (recent)-[:HAS_HISTORY]->(h:History)
                OPTIONAL MATCH (recent)-[:CULTURAL_RELATION]->(c:Culture)
                OPTIONAL MATCH (recent)-[:RELATED_TO_FIGURE]->(f:HistoricalFigure)
                OPTIONAL MATCH (recent)-[:RELATED_TO_EVENT]->(e:HistoricalEvent)
                
                WITH recent, h, c, f, e, u
                
                // 找出有相同历史、文化、人物或事件关联的商品
                OPTIONAL MATCH (otherGoods:Goods)-[:HAS_HISTORY]->(h)
                WHERE otherGoods <> recent AND NOT (u)-[:VIEWED]->(otherGoods)
                
                OPTIONAL MATCH (otherGoods2:Goods)-[:CULTURAL_RELATION]->(c)
                WHERE otherGoods2 <> recent AND NOT (u)-[:VIEWED]->(otherGoods2)
                
                OPTIONAL MATCH (otherGoods3:Goods)-[:RELATED_TO_FIGURE]->(f)
                WHERE otherGoods3 <> recent AND NOT (u)-[:VIEWED]->(otherGoods3)
                
                OPTIONAL MATCH (otherGoods4:Goods)-[:RELATED_TO_EVENT]->(e)
                WHERE otherGoods4 <> recent AND NOT (u)-[:VIEWED]->(otherGoods4)
                
                WITH 
                  COLLECT(DISTINCT otherGoods) + 
                  COLLECT(DISTINCT otherGoods2) + 
                  COLLECT(DISTINCT otherGoods3) + 
                  COLLECT(DISTINCT otherGoods4) AS relatedGoods,
                  recent
                
                UNWIND relatedGoods AS goods
                WHERE goods IS NOT NULL
                
                // 返回相关商品的详细信息和原因
                WITH DISTINCT goods, recent
                OPTIONAL MATCH (goods)-[rel:RELATED_TO]->(recent)
                
                RETURN 
                  goods.id AS id,
                  goods.name AS name,
                  goods.cover AS cover,
                  CASE 
                    WHEN rel IS NOT NULL THEN rel.reasons
                    ELSE ['文化关联'] 
                  END AS reasons,
                  CASE 
                    WHEN rel IS NOT NULL THEN size(rel.reasons)
                         ELSE 1
                  END AS relevanceScore
                ORDER BY relevanceScore DESC
                LIMIT 10
            `;

            const result = await session.run(query, { userId });
            
            // 处理结果为更简洁的对象形式
            return result.records.map(record => ({
                id: record.get('id'),
                name: record.get('name'),
                cover: record.get('cover'),
                reasons: record.get('reasons'),
                relevanceScore: record.get('relevanceScore').toNumber()
            }));
        } finally {
            await session.close();
        }
    }
    
    // 修复知识图谱可视化数据方法
    async getKnowledgeGraphData(goodsId) {
        const session = this.neo4jDriver.session();
        try {
            // 转换goodsId为数字以确保比较正确
            const goodsIdNum = parseInt(goodsId);
            
            // 简化查询，确保基本节点和关系能够返回
            const query = `
                // 从指定商品开始查询
                MATCH (center:Goods)
                WHERE center.id = $goodsId
                
                // 获取商品直接关联的所有节点和关系（一级关系）
                OPTIONAL MATCH (center)-[r1]-(level1)
                WHERE NOT level1:User
                
                // 收集节点和关系
                WITH center, level1, r1
                WHERE level1 IS NOT NULL
                
                // 返回节点
                RETURN 
                    collect(DISTINCT {
                        id: id(center), 
                        label: labels(center)[0], 
                        properties: properties(center),
                        level: 0
                    }) + 
                    collect(DISTINCT {
                        id: id(level1), 
                        label: labels(level1)[0], 
                        properties: properties(level1),
                        level: 1
                    }) AS nodes,
                    
                    // 返回关系
                    collect(DISTINCT {
                        source: id(startNode(r1)), 
                        target: id(endNode(r1)), 
                        type: type(r1),
                        properties: properties(r1)
                    }) AS relationships
            `;
            
            const result = await session.run(query, { goodsId: goodsIdNum });
            
            if (result.records.length === 0) {
                console.log(`知识图谱查询返回空结果，商品ID: ${goodsId}`);
                return { nodes: [], relationships: [] };
            }
            
            const nodes = result.records[0].get('nodes');
            const relationships = result.records[0].get('relationships');
            
            // 过滤掉可能的null值
                return {
                nodes: nodes.filter(n => n && n.id !== null),
                relationships: relationships.filter(r => r && r.source !== null && r.target !== null)
            };
        } catch (error) {
            console.error('获取知识图谱数据失败:', error);
            return { nodes: [], relationships: [] };
        } finally {
            await session.close();
        }
    }

    // 获取热门商品（非个性化推荐）
    async getPopularItems() {
        try {
            // 使用MySQL查询热门商品
            const UserAction = this.sequelize.models.user_actions;
            const Goods = this.sequelize.models.goods;
            const Type = this.sequelize.models.type;
            const Tag = this.sequelize.models.tag;
            const GoodsTag = this.sequelize.models.goods_tag;

            // 获取浏览量最多的商品
            const popularGoods = await UserAction.findAll({
                attributes: [
                    'goods_id', 
                    [this.sequelize.fn('COUNT', this.sequelize.col('goods_id')), 'viewCount']
                ],
                group: ['goods_id'],
                order: [[this.sequelize.literal('viewCount'), 'DESC']],
                limit: 8
            });

            // 提取商品ID
            const goodsIds = popularGoods.map(item => item.goods_id);
            
            if (goodsIds.length === 0) {
                console.log('没有找到热门商品，返回空数组');
                return [];
            }

            try {
                // 查询商品详细信息
                const goodsDetails = await Goods.findAll({
                    where: { id: goodsIds },
                    include: [
                        { model: Type, as: 'category' }
                    ]
                });
                
                // 查询商品的标签
                const goodsTags = await GoodsTag.findAll({
                    where: { goods_id: goodsIds },
                    include: [{
                        model: Tag,
                        attributes: ['id', 'name']
                    }]
                });
                
                // 为每个商品组织标签
                const tagsMap = new Map();
                goodsTags.forEach(gt => {
                    if (!tagsMap.has(gt.goods_id)) {
                        tagsMap.set(gt.goods_id, []);
                    }
                    if (gt.tag) {
                        tagsMap.get(gt.goods_id).push(gt.tag);
                    }
                });
                
                // 为每个商品设置标签
                goodsDetails.forEach(goods => {
                    const tags = tagsMap.get(goods.id) || [];
                    goods.setDataValue('tags', tags);
                });

                // 转换为所需格式
                return goodsDetails.map(goods => {
                    const json = goods.toJSON();
                    return {
                        id: json.id,
                        name: json.name,
                        cover: json.cover,
                        type: json.type,
                        category: json.category,
                        tags: json.tags || [],
                        reasons: ['热门推荐'],
                        relevanceScore: 1
                    };
                });
            } catch (error) {
                console.error('查询商品详情失败:', error);
                // 尝试不带关联的基本查询
                const basicGoodsDetails = await Goods.findAll({
                    where: { id: goodsIds },
                    attributes: ['id', 'name', 'cover', 'type']
                });
                return basicGoodsDetails.map(goods => {
                    const json = goods.toJSON();
                    return {
                        id: json.id,
                        name: json.name,
                        cover: json.cover,
                        type: json.type,
                        tags: [],
                        reasons: ['热门推荐'],
                        relevanceScore: 1
                    };
                });
            }
        } catch (error) {
            console.error('获取热门商品失败:', error);
            // 返回一个空数组作为兜底
            return [];
        }
    }

    // 获取历史文化相关商品（非个性化推荐）
    async getHistoricalItems() {
        const session = this.neo4jDriver.session();
        try {
            // 查询有丰富历史文化关联的商品
            const query = `
                MATCH (g:Goods)
                OPTIONAL MATCH (g)-[:RELATED_TO_FIGURE]->(f:HistoricalFigure)
                OPTIONAL MATCH (g)-[:RELATED_TO_EVENT]->(e:HistoricalEvent)
                OPTIONAL MATCH (g)-[:BELONGS_TO_PERIOD]->(p:Period)
                OPTIONAL MATCH (g)-[:CULTURAL_RELATION]->(c:Culture)
                WITH g, 
                     collect(distinct f) as figures, 
                     collect(distinct e) as events,
                     collect(distinct p) as periods,
                     collect(distinct c) as cultures
                WHERE size(figures) > 0 OR size(events) > 0 OR size(periods) > 0 OR size(cultures) > 0
                RETURN g.id as id, 
                      g.name as name, 
                      g.cover as cover,
                      CASE 
                        WHEN size(figures) > 0 THEN figures[0].name
                        WHEN size(events) > 0 THEN events[0].name
                        WHEN size(periods) > 0 THEN periods[0].name
                        ELSE cultures[0].value
                      END as primaryRelation,
                      size(figures) + size(events) + size(periods) + size(cultures) as culturalRichness
                ORDER BY culturalRichness DESC
                LIMIT 8
            `;

            const result = await session.run(query);
            
            // 处理结果
            return result.records.map(record => ({
                id: record.get('id'),
                name: record.get('name'),
                cover: record.get('cover'),
                reasons: [record.get('primaryRelation') || '文化关联'],
                relevanceScore: record.get('culturalRichness').toNumber()
            }));
        } catch (error) {
            console.error('获取历史文化商品失败:', error);
            // 返回一个空数组作为兜底
            return [];
        } finally {
            await session.close();
        }
    }
}

module.exports = RecommendService;